package com.lintesis.lintesismodel.common.hibernate;

import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;


import com.lintesis.utils.reflection.ReflectionUtils;
import com.trg.search.Filter;
import com.trg.search.Search;
import com.trg.search.SearchResult;
import com.trg.search.hibernate.HibernateSearchProcessor;

@SuppressWarnings("unchecked")
@Entity
public class GenericDAO<T extends BussinessObject> extends Search
{

	/**
	 * 
	 */
	@Id
	@GeneratedValue
	private static final long serialVersionUID = -3345860406986408937L;
	private Session session = null;

	protected GenericDAO()
	{
	}

	public GenericDAO(Session session)
	{
		this.session = session;
	}

	public void save(T bo)
	{

		session.save(bo);

	}

	public void saveOrUpdate(T bo)
	{

		try
		{

			session.saveOrUpdate(bo);
		} catch (HibernateException e)
		{
			// e.printStackTrace();
			session.merge(bo);
		}
	}

	public void update(T bo)
	{

		try
		{
			session.update(bo);
		} catch (Exception ex)
		{
			session.merge(bo);
		}
	}

	public void delete(T bo)
	{

//		session.flush();
		session.delete(bo);

	}

	public T load(T bo)
	{

		T retorno = null;

		retorno = (T) session.load(bo.getClass(), bo.getId());
		return retorno;
	}

	public List<T> getByBussinessObject(T bussinessObject) throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException,
			InvocationTargetException, InstantiationException
	{
		return getByBussinessObject(bussinessObject, 0, 0);
	}

	public SearchResult<T> getSRByBussinessObject(T bussinessObject) throws SecurityException, IllegalArgumentException, NoSuchMethodException,
			IllegalAccessException, InvocationTargetException, InstantiationException
	{
		return getSRByBussinessObject(bussinessObject, 0, 0);
	}

	// This search it's case sensitive
	public SearchResult<T> getSRByHashMap(HibernateSearchObject<T> hso, int start, int pageSize, HashMap<String, Object> parameters)
	{
		return getSRByHashMap(hso, start, pageSize, parameters, true);
	}

	public SearchResult<T> getSRByHashMap(HibernateSearchObject<T> hso, int start, int pageSize, HashMap<String, Object> parameters, boolean caseSensitive)
	{
		for (String key : parameters.keySet())
		{

			if (parameters.get(key) != null && !parameters.get(key).equals("") && !parameters.get(key).equals("%%"))
				if (parameters.get(key) instanceof String)
				{
					if (caseSensitive)
						hso.addFilterLike(key, parameters.get(key).toString());
					else
						hso.addFilterILike(key, parameters.get(key).toString());

				} else
				{
					hso.addFilterEqual(key, parameters.get(key));
				}

		}
		return getSRBySearchObject(hso, 0, pageSize);
	}

	public SearchResult<T> getSRByBussinessObject(Object object, int start, int pageSize) throws SecurityException, IllegalArgumentException,
			NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException
	{
		setSearchClass(object.getClass());

		SessionFactory sf = session.getSessionFactory();

		HibernateSearchProcessor hsp = HibernateSearchProcessor.getInstanceForSessionFactory(sf);

		setFirstResult(start);
		if (pageSize != 0)
			setMaxResults(pageSize);

		HashMap<String, Object> hashMap = ReflectionUtils.toHashMap(object);
		for (String field : hashMap.keySet())
		{
			if (hashMap.get(field) != null && !(hashMap.get(field) instanceof Set))
			{
				addFilter(Filter.equal(field, hashMap.get(field)));
			}

		}
		SearchResult<T> list = hsp.searchAndCount(session, this);

		return list;
	}

	public List<T> getByBussinessObject(Object object, int start, int pageSize) throws SecurityException, IllegalArgumentException, NoSuchMethodException,
			IllegalAccessException, InvocationTargetException, InstantiationException
	{

		setSearchClass(object.getClass());

		SessionFactory sf = session.getSessionFactory();

		HibernateSearchProcessor hsp = HibernateSearchProcessor.getInstanceForSessionFactory(sf);

		setFirstResult(start);
		if (pageSize != 0)
			setMaxResults(pageSize);

		HashMap<String, Object> hashMap = ReflectionUtils.toHashMap(object);
		for (String field : hashMap.keySet())
		{
			if (hashMap.get(field) != null && !(hashMap.get(field) instanceof Collection) && !(hashMap.get(field) instanceof BussinessObject)
					&& !(hashMap.get(field) instanceof Date))
			{
				if (hashMap.get(field) instanceof String)
					addFilter(Filter.ilike(field, (String) hashMap.get(field)));
				else
					addFilter(Filter.equal(field, hashMap.get(field)));

			}
			if (hashMap.get(field) != null && hashMap.get(field) instanceof BussinessObject)
			{
				addFilter(Filter.equal(field + ".id", ((BussinessObject) (hashMap.get(field))).getId()));
			}
		}
		List<T> list = hsp.search(session, this);
		// t.
		return list;
	}

	public List<T> getBySearchObject(HibernateSearchObject so, int start, int pageSize)
	{

		SessionFactory sf = session.getSessionFactory();

		HibernateSearchProcessor hsp = HibernateSearchProcessor.getInstanceForSessionFactory(sf);

		so.setFirstResult(start);
		so.setMaxResults(pageSize);

		List<T> list = hsp.search(session, so);

		return list;
	}

	public SearchResult<T> getSRBySearchObject(HibernateSearchObject<T> so, int start, int pageSize)
	{

		SessionFactory sf = session.getSessionFactory();

		HibernateSearchProcessor hsp = HibernateSearchProcessor.getInstanceForSessionFactory(sf);

		so.setFirstResult(start);
		so.setMaxResults(pageSize);
		// Transaction t = ss.beginTransaction();
		SearchResult<T> searchresult = hsp.searchAndCount(session, so);

		return searchresult;
	}

}
